package {{pack}}.logbook;

import static java.util.stream.Collectors.joining;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.zalando.logbook.Correlation;
import org.zalando.logbook.HttpLogFormatter;
import org.zalando.logbook.HttpRequest;
import org.zalando.logbook.HttpResponse;
import org.zalando.logbook.Precorrelation;

public class CompleteCurlHttpLogFormatter implements HttpLogFormatter{

  private final HttpLogFormatter fallback;

  public CompleteCurlHttpLogFormatter() {
      this(new CompleteHttpLogFormatter());
  }

  public CompleteCurlHttpLogFormatter(final HttpLogFormatter fallback) {
      this.fallback = fallback;
  }

  @Override
  public String format(final Precorrelation<HttpRequest> precorrelation) throws IOException {
      
      final HttpRequest request = precorrelation.getRequest();
      final List<String> command = new ArrayList<>();
     
      List<String> multiFormat = new ArrayList<>();
      multiFormat.add(fallback.format(precorrelation));
      multiFormat.add("\n-------------------------------------------------------------------------------\n");
      command.add("curl");
      command.add("-v"); // TODO optional?

      command.add("-X"+request.getMethod());

      command.add(quote(request.getRequestUri()));
      
      boolean isFormReq = FormBodyConstructs.isRemoteFormRequest(request);

      request.getHeaders().forEach((header, values) -> {
          values.forEach(value -> {
              if (isFormReq && header.equalsIgnoreCase("Content-Length")) {
                 return;
              }
              command.add("-H");
              command.add(quote(header + ": " + value));
          });
      });

      final String body = isFormReq ? FormBodyConstructs.getFormBody(request) : request.getBodyAsString();

      if (!body.isEmpty()) {
          command.add("--data-binary");
          command.add(quote(body));
      }

      multiFormat.add(command.stream().collect(joining(" ")));
      return multiFormat.stream().collect(joining(""));
  }

  private static String quote(final String s) {
      return "'" + escape(s) + "'";
  }

  private static String escape(final String s) {
      return s.replace("'", "\\'");
  }

  @Override
  public String format(final Correlation<HttpRequest, HttpResponse> correlation) throws IOException {
      return fallback.format(correlation);
  }


}
